/*
 * Copyright (c) 2005, 2014 vacoor
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package org.vacoor.nothing.web.spring.web.view;

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.springframework.web.servlet.view.document.AbstractExcelView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 两种方式:
 * 1.
 * Map model = ...
 * new ExcelView();
 * return new ModelAndView(excelView, model);
 * 2.
 * <bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
 *    <property name="basename" value="views" />
 * </bean>
 * 用于多个视图集成时,ResourceBundleViewResolver是通过解析资源文件来解析请求输出文件的。
 <property name="basename" value="views"></property>,即表示在/WEB-INF/classes路径下有一个
 views.properties文件,本例中views.properties的内容为
 welcome.(class)=org.springframework.web.servlet.view.velocity.VelocityView
 welcome.url=welcome.vm
 freemarker.(class)=org.springframework.web.servlet.view.freemarker.FreeMarkerView
 freemarker.url=freemarker.ftl
 */
public class ExcelView<D> extends AbstractExcelView {
    private static final String DEFAULT_HEADERS_KEY = "eheaders";
    private static final String DEFAULT_DATA_KEY = "edata";
    private static final String DEFAULT_SHEET_NAME = "sheet1";
    private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";

    private String headersKey = DEFAULT_HEADERS_KEY;
    private String dataKey = DEFAULT_DATA_KEY;
    private String sheetName = DEFAULT_SHEET_NAME;
    private String dateFormat = DEFAULT_DATE_FORMAT;



    @Override
    protected void buildExcelDocument(Map<String, Object> model, HSSFWorkbook workbook, HttpServletRequest request, HttpServletResponse response) throws Exception {
        String[] headers = (String[]) model.get(headersKey);
        List<D> data = (List<D>) model.get(dataKey);
        HSSFSheet sheet = workbook.getSheet(sheetName);

        if (sheet == null) {
            sheet = workbook.createSheet(sheetName);
        }

        // poi 不像 jxl 会自动设置style, poi 日期必须自行设置style
        CellStyle dateStyle = workbook.createCellStyle();
        dateStyle.setDataFormat(workbook.createDataFormat().getFormat(dateFormat));

        int i = 0;
        if (headers != null && headers.length > 0) {
            for (; i < headers.length; i++) {
                setText(getCell(sheet, 0, i), headers[i]);
            }
            sheet.createFreezePane(0, 1, 0, 1); // 冻结首行
        }

        for (int r = 0; r < data.size(); r++) {
            D d = data.get(r);
            Object[] values = buildExcelRowData(d);
            Row row = sheet.createRow(i + 1);

            if (values == null) {
                continue;
            }

            // 写入列
            for (int c = 0; c < values.length; c++) {
                Object value = values[c];
                if (value == null) {
                    continue;
                }

                Cell cell = row.createCell(c);

                if (value instanceof Boolean) {
                    cell.setCellType(Cell.CELL_TYPE_BOOLEAN);
                    cell.setCellValue((Boolean) value);
                } else if (value instanceof Number) {
                    cell.setCellType(Cell.CELL_TYPE_NUMERIC);
                    cell.setCellValue(((Number) value).doubleValue());
                } else if (value instanceof Date) {
                    cell.setCellType(Cell.CELL_TYPE_NUMERIC);
                    cell.setCellValue((Date) value);
                    cell.setCellStyle(dateStyle);
                } else if (value instanceof Calendar) {
                    cell.setCellType(Cell.CELL_TYPE_NUMERIC);
                    cell.setCellValue((Calendar) value);
                    cell.setCellStyle(dateStyle);
                } else {
                    cell.setCellType(Cell.CELL_TYPE_STRING);
                    cell.setCellValue(value.toString());
                }
            }
        }

        // 因为父类将 renderMergedOutputModel 声明为 final 所以只好放这里了
        Object filename = model.get("filename");
        // TODO
    }

    private Object[] buildExcelRowData(D d) {
        return new Object[0];
    }
}
